package gui;



import java.util.GregorianCalendar;

import msjcalendar.Calendar;
import msjcalendar.CalendarFile;
import msjcalendar.Event;

import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;

/**
 * @author sebastian, markus
 *
 */
public class MainComposite extends Composite {
	
	/**
	 * Log-window.
	 */
	private Text outputText;
	/**
	 * layoutdata for diffrent composites.
	 */
	private FormLayout layout;
	/**
	 * toolbar for new Event and menu.
	 */
	private ToolBar tb;
	/**
	 * dateChangeComposite.
	 */
	private DateChangeComposite dateChangeComposite;
	/**
	 * 
	 */
	private SashForm sash;
	/**
	 * 
	 */
	private SashForm vsash;
	/**
	 * tabFolder for week, month.
	 */
	private TabFolder tabFolder;
	/**
	 * selected calendarFile.
	 */
	private CalendarFile calendarFile;
	/**
	 * composite for edit events.
	 */
	private EventComposite eventComposite;
	/**
	 * weekView.
	 */
	private WeekViewComposite weekViewComposite;
	/**
	 * monthView.
	 */
	private MonthViewComposite monthViewComposite; 
	
	
	/*-----------------------------------------------------------------------------------*/
	
	/**
	 * @param parent parent composite
	 * @param style SWT Styles
	 */
	public MainComposite(final Composite parent, final int style) {
		super(parent, style);
		this.calendarFile = new CalendarFile();
		this.calendarFile.setCalendar(new Calendar());
		layout = new FormLayout();
		Device device = Display.getCurrent();
		Color white = new Color(device, 255, 255, 255);
		this.setLayout(layout);
		this.tb = this.createToolBar();
		this.tb.redraw();
		this.dateChangeComposite = createDate();
		
		this.sash = this.createSash();
		this.vsash = new SashForm(sash, SWT.VERTICAL | SWT.SMOOTH);
		FormData data = new FormData();
		data.top = new FormAttachment(this.dateChangeComposite, 3);
		data.bottom = new FormAttachment(100, 0);
		data.left = new FormAttachment(0, 0);
		data.right = new FormAttachment(100, 0);
		sash.setLayoutData(data);
		this.tabFolder = this.createTabFolder();
		this.tabFolder.redraw();
		ScrolledComposite sc = new ScrolledComposite(sash, SWT.H_SCROLL | SWT.V_SCROLL);
	    this.eventComposite = new EventComposite(sc, SWT.BORDER);
	    sc.setMinSize(new Point(230, 400));
	    sc.setContent(eventComposite);
	    sc.setExpandHorizontal(true);
	    sc.setExpandVertical(true);
		sash.setWeights(new int[]{7, 0});
		outputText = new Text(vsash, SWT.BORDER | SWT.READ_ONLY | SWT.MULTI | SWT.V_SCROLL);
		outputText.setBackground(white);
		vsash.setWeights(new int[]{10, 1});
		
		eventComposite.getDeleteButton().addSelectionListener(new SelectionListener() {

			@Override
			public void widgetDefaultSelected(final SelectionEvent arg0) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void widgetSelected(final SelectionEvent arg0) {
				if (eventComposite.getEvent() != null) {
					calendarFile.getCalendar().deleteEvent(eventComposite.getEvent());
					weekViewComposite.refresh();
					monthViewComposite.refresh();
					sash.setWeights(new int[]{7, 0});
					try {
						calendarFile.save();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
			
		});
		
		eventComposite.getConfirmButton().addSelectionListener(new SelectionListener() {
			@Override
			public void widgetSelected(final SelectionEvent arg0) {
				if (eventComposite.verify()) {
					if (eventComposite.getEvent() != null) {
						calendarFile.getCalendar().deleteEvent(eventComposite.getEvent());
						outputText.append(formatString("Event modified."));
					} else {
						outputText.append(formatString("New Event created."));
					}
					Event event = eventComposite.parseEvent();
					calendarFile.getCalendar().createEvent(event);
					eventComposite.setEvent(event);
					weekViewComposite.refresh();
					monthViewComposite.refresh();
					try {
						calendarFile.save();
						eventComposite.endEditMode();
					} catch (Exception e) {
						outputText.append(formatString(e.toString()));
						e.printStackTrace();
					}
				} else {
					outputText.append(formatString("Invalid Event: ".concat(eventComposite.getVerificationMessage())));
				}
			}
			
			@Override
			public void widgetDefaultSelected(final SelectionEvent arg0) {
				// TODO Auto-generated method stub
				
			}
		});
		
		eventComposite.getCloseButton().addSelectionListener(new SelectionListener() {		
			@Override
			public void widgetSelected(final SelectionEvent arg0) {
				sash.setWeights(new int[]{7, 0});
			}
			@Override
			public void widgetDefaultSelected(final SelectionEvent arg0) {
			}
		});
		outputText.append(getTimeStamp() + "\tProgram succesfully started.");
		this.weekViewComposite.setDate(new GregorianCalendar());
	}
	
	/**
	 * @return created tabfolder
	 */
	private TabFolder createTabFolder() {
		final TabFolder tabfolder = new TabFolder(vsash, SWT.NONE);
		TabItem tab0 = new TabItem(tabfolder, SWT.HORIZONTAL);
		tab0.setText("Week");
		this.weekViewComposite = new WeekViewComposite(tabfolder, SWT.NONE, this.calendarFile.getCalendar(), 
				new ISelectionChangedListener() {
			
			@Override
			public void selectionChanged(final SelectionChangedEvent e) {
				try {
					Event event = ((Event) (((TableViewer) (e
							.getSource())).getTable()
							.getItem(
									((TableViewer) (e.getSource()))
											.getTable()
											.getSelectionIndex())
							.getData()));
					eventComposite.setEvent(event);
					sash.setWeights(new int[]{7, 3});
				} catch (Exception ex) {
					ex.printStackTrace();
				}
			}
		});
	    tab0.setControl(this.weekViewComposite);
		TabItem tab1 = new TabItem(tabfolder, SWT.HORIZONTAL);
		tab1.setText("Month");
		this.monthViewComposite = new MonthViewComposite(tabfolder, SWT.NONE, this.calendarFile.getCalendar(), 
				new ISelectionChangedListener() {
			
			@Override
			public void selectionChanged(final SelectionChangedEvent e) {
				try {
					Event event = ((Event) (((TableViewer) (e
							.getSource())).getTable()
							.getItem(
									((TableViewer) (e.getSource()))
											.getTable()
											.getSelectionIndex())
							.getData()));
					eventComposite.setEvent(event);
					sash.setWeights(new int[]{7, 3});
				} catch (Exception ex) {
					ex.printStackTrace();
				}
			}
		});
		this.monthViewComposite.setDate(new GregorianCalendar());
	    tab1.setControl(this.monthViewComposite);
	    tabfolder.addSelectionListener(new SelectionListener() {
			
			@Override
			public void widgetSelected(final SelectionEvent arg0) {
				if (tabfolder.getSelectionIndex() == 0) {
					dateChangeComposite.setMode(GregorianCalendar.WEEK_OF_YEAR);
				} else {
					dateChangeComposite.setMode(GregorianCalendar.MONTH);
				}
			}
			
			@Override
			public void widgetDefaultSelected(final SelectionEvent arg0) {
				// TODO Auto-generated method stub
				
			}
		});
	    return tabfolder;
	}
	
	/**
	 * @return created sash
	 */
	private SashForm createSash() {
		SashForm sash0 = new SashForm(this, SWT.HORIZONTAL | SWT.SMOOTH);
		FormData data2 = new FormData();
		data2.top = new FormAttachment(0, 0);
		data2.bottom = new FormAttachment(100, 0);
		data2.left = new FormAttachment(0, 0);
		data2.right = new FormAttachment(100, 0);
		//sash.setLayoutData(data2);
		
		return sash0;
	}
	
	/**
	 * @return created date
	 */
	private DateChangeComposite createDate() {
		final DateChangeComposite date1 = new DateChangeComposite(this, SWT.BORDER);
	    FormData data1 = new FormData();
	    data1.top = new FormAttachment(0, 2);
	    data1.left = new FormAttachment(0, 2);
		date1.setLayoutData(data1);
		date1.addListener(SWT.Modify, new Listener() {
			@Override
			public void handleEvent(final org.eclipse.swt.widgets.Event event) {
				weekViewComposite.setDate(dateChangeComposite.getDate());
				weekViewComposite.refresh();
				monthViewComposite.setDate(dateChangeComposite.getDate());
				monthViewComposite.refresh();
			}
		});
		
		return date1;
	}
	
	/**
	 * @return created toolbar
	 */
	private ToolBar createToolBar() {
		final ToolBar tb0 = new ToolBar(this, SWT.HORIZONTAL);
		FormData data0 = new FormData();
	    data0.top = new FormAttachment(0, 0);
	    data0.right = new FormAttachment(100, 0);
		tb0.setLayoutData(data0);
		ToolItem button = new ToolItem(tb0, SWT.PUSH);
		button.setText("New Event");
		button.addSelectionListener(new SelectionListener() {
			
			@Override
			public void widgetSelected(final SelectionEvent arg0) {
				eventComposite.setEvent(null);
				outputText.append(formatString("New Event created."));
				sash.setWeights(new int[]{7, 3});
				eventComposite.startEditMode();
			}
			
			@Override
			public void widgetDefaultSelected(final SelectionEvent arg0) {
				// TODO Auto-generated method stub
				
			}
		});
		ToolItem item = new ToolItem(tb0, SWT.DROP_DOWN);
		item.setText("Menu");
		
		item.addSelectionListener(new SelectionAdapter() {
			private Menu dropdownMenu = null;
			
			@Override
			public void widgetSelected(final SelectionEvent e) {
				if (dropdownMenu == null) {
					dropdownMenu = new Menu(tb0.getParent());
					tb0.getShell().setMenu(dropdownMenu);
					MenuItem button0 = new MenuItem(dropdownMenu, SWT.PUSH);
					button0.setText("New");
					new MenuItem(dropdownMenu, SWT.SEPARATOR);
					MenuItem button1 = new MenuItem(dropdownMenu, SWT.PUSH);
					button1.setText("Save");
					button1.addSelectionListener(new SelectionListener() {
						@Override
						public void widgetSelected(final SelectionEvent arg0) {
							try {
								outputText.append(formatString("Saving File..."));
								calendarFile.save();
								outputText.append(formatString("File succesfully saved!"));
							} catch (Exception e) {
								outputText.append(e.toString());
							}
							
						}
						@Override
						public void widgetDefaultSelected(final SelectionEvent arg0) {
							// TODO Auto-generated method stub
						}
					});
					MenuItem button2 = new MenuItem(dropdownMenu, SWT.PUSH);
					button2.setText("Load");
					button2.addSelectionListener(new SelectionListener() {
						@Override
						public void widgetSelected(final SelectionEvent arg0) {
							try {
								outputText.append(formatString("Loading File..."));
								calendarFile.load();
								outputText.append(formatString("File succesfully loaded!"));
								weekViewComposite.setCalendar(calendarFile.getCalendar());
								monthViewComposite.setCalendar(calendarFile.getCalendar());
								weekViewComposite.refresh();
								monthViewComposite.refresh();
							} catch (Exception e) {
								outputText.append(formatString(e.toString()));
							}
						}
						@Override
						public void widgetDefaultSelected(final SelectionEvent arg0) {
							// TODO Auto-generated method stub
						}
					});
					new MenuItem(dropdownMenu, SWT.SEPARATOR);
					final MenuItem checkButton0 = new MenuItem(dropdownMenu, SWT.CHECK);
					checkButton0.setText("View Log");
					checkButton0.addSelectionListener(new SelectionAdapter() {
						@Override
						public void widgetSelected(final SelectionEvent e) {
							if (!checkButton0.getSelection()) {
								vsash.setWeights(new int[]{1, 0});
							} else {
								vsash.setWeights(new int[]{10, 1});
							}
						}
					});
					checkButton0.setSelection(true);
					MenuItem button3 = new MenuItem(dropdownMenu, SWT.PUSH);
					button3.setText("Exit");
					button3.addSelectionListener(new SelectionAdapter() {
						@Override
						public void widgetSelected(final SelectionEvent e) {
							tb0.getShell().close();
						}
					});
				}
				
				if (e.detail == SWT.ARROW) {
					final ToolItem toolItem = (ToolItem) e.widget;
					final ToolBar toolBar = toolItem.getParent();
					
					Point point = toolBar.toDisplay(new Point(e.x, e.y));
					dropdownMenu.setLocation(point);
					dropdownMenu.setVisible(true);
				}
			}
		});
		return tb0;
	}
	
	/**
	 * @param s input string
	 * @return string formatted for log-output
	 */
	private String formatString(final String s) {
		String result = s.replace("\n", "\n\t\t\t");
		return "\n".concat(this.getTimeStamp()).concat("\t").concat(result);
	}
	/**
	 * @return timestamp string
	 */
	private String getTimeStamp() {
		GregorianCalendar now = new GregorianCalendar();
		return String.format("[%02d:%02d:%02d]", 
				now.get(GregorianCalendar.HOUR_OF_DAY),
				now.get(GregorianCalendar.MINUTE),
				now.get(GregorianCalendar.SECOND));
	}
}
